using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom.Compiler;

namespace SharpMud.Server.Systems.Scripting
{
    /// <summary>
    /// Provides static mechanisms for determining and recognizing .NET CodeDom compatible
    /// scripting options, through the use of CodeDomProvider. Compiled with a static
    /// preset of languages, but is extensible at runtime to recognize others.
    /// </summary>
    /// <remarks>
    /// Currently compiled, it supports C#, VB.NET, and VJ#.
    /// </remarks>
    public static class LanguageRecognition
    {
        private static Dictionary<string, CodeDomProvider> _FileExtensions;

        static LanguageRecognition()
        {
            _InitializeLanguageProviders();
        }

        #region Language Recognition
        /// <summary>
        /// Initialize the language recognition utility with default languages, including
        /// languages registered with the Global Assembly Cache.
        /// </summary>
        private static void _InitializeLanguageProviders()
        {
            _FileExtensions = new Dictionary<string, CodeDomProvider>();

            //Pull languages off of the system's registered CodeDomProvider's
            CompilerInfo[] registeredSystemCompilers;
            try
            {
                registeredSystemCompilers = CodeDomProvider.GetAllCompilerInfo();
                foreach (CompilerInfo compiler in registeredSystemCompilers)
                {
                    CodeDomProvider compilerProvider=null;
                    try
                    {
                        compilerProvider = compiler.CreateProvider();
                    }
                    catch { }
                    if (compilerProvider != null)
                        RegisterLanguage(compilerProvider);
                }
            }
            catch { }

            //Make sure that C#, VB.NET, and VJ# are in the language recognition utility
            RegisterLanguage(new Microsoft.CSharp.CSharpCodeProvider());
            RegisterLanguage(new Microsoft.VisualBasic.VBCodeProvider());
            RegisterLanguage(new Microsoft.VJSharp.VJSharpCodeProvider());
        }

        /// <summary>
        /// Register a CodeDomProvider with the language recognition utility,
        /// </summary>
        /// <param name="codeProvider">The CodeDomProvider for the programming language to be
        /// registered with the language recognition utility.</param>
        public static void RegisterLanguage(System.CodeDom.Compiler.CodeDomProvider codeProvider)
        {
            string newExt = codeProvider.FileExtension.Trim().ToLower();
            if (newExt.StartsWith(".")) { newExt = newExt.Substring(1); }
            else if (newExt.StartsWith("*.")) { newExt = newExt.Substring(2); }

            if (_FileExtensions.ContainsKey(newExt) || _FileExtensions.ContainsValue(codeProvider))
            {
                return;
            }
            _FileExtensions.Add(newExt, codeProvider);
        }

        /// <summary>
        /// Determines and provides an instance of the needed CodeDomProvider to compile or
        /// parse the given source code file.
        /// </summary>
        /// <param name="file">The file for which the CodeDomProvider is to be determined</param>
        /// <returns>Returns an appropriate instance of CodeDomProvider for the source 
        /// code file, if one can be determined. Otherwise, returns null.</returns>
        public static System.CodeDom.Compiler.CodeDomProvider GetLanguageOfFile(System.IO.FileInfo file)
        {
            string ext = file.Extension.Trim().ToLower();

            if (!_FileExtensions.ContainsKey(ext))
                return null;
            else
                return _FileExtensions[ext];
        }
        #endregion
    }
}
